﻿using pdfer.FileObjects;
using pdfer.PdfObjecs;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace pdfer.Syntax
{
    internal static class PdfParserUtils
    {
        internal static readonly Encoding Encoding = Encoding.ASCII;

        #region 3rd LoadXref&Tailer
        internal static (XRefTable[] xrefInfo, Dictionary<String, (Int32, Int32)> map, TrailerDictionary trailerObj) ParseXRef2andTailerV3(Stream pdf)
        {
            // 尾部对象主要是需要获取 Root Info Prev 其他的不重要
            // 先找到第一个文件尾部
            // 读取第一个xref开始的位置
            pdf.Seek(-1, SeekOrigin.End);
            while (true)
            {
                var bytes = ReadLineBack(pdf);
                if (Encoding.GetString(bytes) == "%%EOF")
                {
                    break;
                }
                if (pdf.Position == 0)
                {
                    throw new Exception("未找到文件结束标记");
                }
            }
            String? lastLine = null;
            while (true)
            {
                var bytes = ReadLineBack(pdf);

                var _str = Encoding.GetString(bytes);
                if (_str == "startxref")
                {
                    break;
                }
                if (pdf.Position == 0)
                {
                    throw new Exception("未找到 startxref 标记");
                }
                lastLine = _str;
            }
            var xrefs = new List<XRefTable>();
            Dictionary<String, (Int32, Int32) > mapInfos = [];
            Dictionary<String, Object> trailerObj = [];
            var xrefOffset = Int32.Parse(lastLine);
            while (true) 
            {
                // XRefTable[] xrefInfo, Dictionary<String, Int32> map, Dictionary trailer 
                var (xrefInfo, mapInfo, _trailerObj) = ParseXrefV3(pdf, xrefOffset);
                xrefs.AddRange(xrefInfo);
                foreach (var itm in mapInfo)
                {
                    mapInfos.TryAdd(itm.Key, itm.Value);
                }
                foreach (var itm in _trailerObj)
                {
                    trailerObj.TryAdd(itm.Key, itm.Value);
                }

                // 一定是一个字典 包含了二进制流
                if (_trailerObj.TryGetValue(PdfName.Key_Prev, out var _val) && Int32.TryParse(_val.ToString(), out var _val2))
                {
                    xrefOffset = _val2;
                }
                else
                {
                    break;
                }

            }
            return (xrefs.ToArray(), mapInfos, TrailerDictionary.Create(trailerObj));
        }

        private static (XRefTable[] xrefInfo, Dictionary<String, (Int32, Int32)> mapInfo, Dictionary<String, Object> trailObj) ParseXrefV3(Stream pdf, Int32 offset)
        {
            pdf.Seek(offset, SeekOrigin.Begin);
            var first = ReadLine(pdf, 22);
            if (first[0] == 0x78 && first[1] == 0x72 && first[2] == 0x65 && first[3] == 0x66)
            {
                List<XRefTable> xRefTables = [];
                //pdf.Seek(offset + 4, SeekOrigin.Begin);
                XRefTable xRefTable = null;
                while (true)
                {
                    var buff = ReadLine(pdf, 22);
                    if (buff.Length < 4)
                    {
                        continue;
                    }
                    var line = Encoding.GetString(buff);
                    if (line.StartsWith("trailer"))
                    {
                        // 移动回去
                        pdf.Position = pdf.Position - buff.Length + "trailer".Length;
                        break;
                    }
                    var xrefarr = line.Split(' ');
                    Int32.TryParse(xrefarr[0], out Int32 val1);
                    Int32.TryParse(xrefarr[1], out Int32 val2);
                    if (xrefarr.Length == 2)
                    {
                        xRefTable = new XRefTable(val1, val2);
                        xRefTables.Add(xRefTable);
                    }
                    else
                    {
                        var refId = xRefTable.StartId + xRefTable.ObjOffsetInfos.Count;
                        xRefTable.ObjOffsetInfos.Add(new ObjOffsetInfo
                        {
                            Offset = val1,
                            Version = val2,
                            RefFlag = xrefarr[2][0],
                            RefId = refId
                        });
                    }
                }
                // 读取直到 startxref
                var engine = new PSCompilationEngineV2();
                engine.ParseToPdfFileObject(pdf, pdf.Position);
                var fileObj = engine.PdfFileObject;
                var dic = new Dictionary<String, (Int32, Int32)>();
                foreach (var xrefTable in xRefTables)
                {
                    for (var i = 0; i < xrefTable.ObjOffsetInfos.Count; i++)
                    {
                        var xref = xrefTable.ObjOffsetInfos[i];
                        var key = $"{xref.RefId} 0";
                        // 后生成的对象信息覆盖前面的所以TryAdd
                        dic.TryAdd(key, (xref.Offset, -1));
                    }
                }
                return (xRefTables.ToArray(), dic, fileObj.Dictionary);

            }
            else
            {
                List<XRefTable> xRefTables = [];
                var engine = new PSCompilationEngineV2();
                engine.ParseToPdfFileObject(pdf, offset);
                var fileObj = engine.PdfFileObject;
                xRefTables.AddRange(ParseXrefByStream(fileObj));
                var dic = new Dictionary<String, (Int32, Int32)>();
                foreach (var xrefTable in xRefTables)
                {
                    for (var i = 0; i < xrefTable.ObjOffsetInfos.Count; i++)
                    {
                        var xref = xrefTable.ObjOffsetInfos[i];
                        var key = $"{xref.RefId} 0";
                        if (xref.ObjStmId >-1)
                        {
                            // 后生成的对象信息覆盖前面的所以TryAdd
                            dic.TryAdd(key, (xref.ObjStmId, xref.Index));
                        }
                        else
                        {
                            // 后生成的对象信息覆盖前面的所以TryAdd
                            dic.TryAdd(key, (xref.Offset, -1));
                        }
                    }
                    
                }
                return (xRefTables.ToArray(), dic, fileObj.Dictionary);
            }
        }
        #endregion

        #region 2nd LoadXref&Tailer
        [Obsolete("建议使用 PdfParserUtils.ParseXRef2andTailerV3")]
        internal static (XRefTable[] xrefInfo, Dictionary<String, Int32> map, TrailerDictionary trailerObj) ParseXref2andTailer(Stream pdf)
        {
            // 尾部对象主要是需要获取 Root Info Prev 其他的不重要
            // 先找到第一个文件尾部
            // 读取第一个xref开始的位置
            pdf.Seek(-1, SeekOrigin.End);
            while (true)
            {
                var bytes = ReadLineBack(pdf);
                if (Encoding.GetString(bytes) == "%%EOF")
                {
                    break;
                }
                if(pdf.Position == 0)
                {
                    throw new Exception("未找到文件结束标记");
                }
            }
            var lastLine = "";
            while (true)
            {
                var bytes = ReadLineBack(pdf);

                var _str = Encoding.GetString(bytes);
                if (_str == "startxref")
                {
                    break;
                }
                lastLine = _str;
            }
            var xrefOffset = Int32.Parse(lastLine); // 这里转换失败需要报错
            var xrefs = new List<XRefTable>();
            var mapInfos = new Dictionary<String, Int32>();
            TrailerDictionary tailerObj = null;
            while (true)
            {
                // xref表 对象id映射表 尾部对象
                var (xrefInfo, mapInfo, tailObj) = ParseXref(pdf, xrefOffset);
                xrefs.AddRange(xrefInfo);
                foreach(var itm in  mapInfo)
                {
                    mapInfos.Add(itm.Key, itm.Value);
                }
                if(tailObj != null)
                {
                    // 新的xref读取方式
                    var __tailerObj = TrailerDictionary.Create(tailObj.Dictionary);
                    return (xrefInfo.ToArray(), mapInfo, __tailerObj);
                }
                // 读取尾部对象
                List<String> lines = [];
                var objStrs = new List<String>();
                var statDic = false;
                while (true)
                {
                    var lineByes = ReadLine(pdf);
                    var line = Encoding.GetString(lineByes).TrimEnd('\n').TrimEnd('\r');
                    if (line.StartsWith("trailer"))
                    {
                        statDic = true;
                        line = line.Substring(7);
                    }
                    if (statDic && !String.IsNullOrEmpty(line))
                    {
                        objStrs.Add(line);
                        if (line.EndsWith(">>"))
                        {
                            break;
                        }
                    }
                    if(lineByes.Length == 0)
                    {
                        // 应该要报错正常不会读到文件结尾
                        break;
                    }
                }
                var dic = ParseFileTrailerObject(String.Join(' ', objStrs));
                var _tailerObj = TrailerDictionary.Create(dic);
                if(tailerObj == null)
                {
                    tailerObj = _tailerObj;
                }
                else
                {
                    if (String.IsNullOrEmpty(tailerObj.Root))
                    {
                        tailerObj.Root =_tailerObj.Root;
                    }
                    if (String.IsNullOrEmpty(tailerObj.Info))
                    {
                        tailerObj.Info = _tailerObj.Info;
                    }
                }
                if(_tailerObj.Prev == 0)
                {
                    break;
                }
                xrefOffset = tailerObj.Prev;
            }
            return (xrefs.ToArray(), mapInfos, tailerObj);
        }
        #endregion
        /// <summary>
        /// 读取文件尾部信息<br/>
        /// todo: 对于有多个文件结束符的pdf文件还未处理
        /// </summary>
        /// <param name="pdf"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        [Obsolete("建议使用 PdfParserUtils.ParseXref2andTailer")]
        internal static PdfFileTrailer ParseFileTrailer(Stream pdf)
        {
            var result = new PdfFileTrailer();

            pdf.Seek(-1, SeekOrigin.End);
            while (true)
            {
                var bytes = ReadLineBack(pdf);
                if (Encoding.GetString(bytes) == "%%EOF")
                {
                    break;
                }
            }
            var stack = new Stack<String>();
            while (true)
            {
                var bytes = ReadLineBack(pdf);
                var line = Encoding.ASCII.GetString(bytes);
                stack.Push(line);
                if (line.StartsWith("trailer"))
                {
                    break;
                }
            }
            var lines = new List<String>();
            while (stack.Count > 0)
            {
                lines.Add(stack.Pop());
            }

            for (int i = 0; i < lines.Count; i++)
            {
                var line = lines[i];
                switch (line)
                {
                    case "trailer":
                        // 下一行是尾部对象字典
                        // 获取完整的对象字符串
                        var objstr = new List<String>();
                        while (true)
                        {
                            i++;
                            line = lines[i];
                            objstr.Add(line);
                            if (line.EndsWith(">>"))
                            {
                                break;
                            }
                        }
                        var dic = ParseFileTrailerObject(String.Join(' ', objstr));
                        result.TrailerObj = dic;
                        break;
                    case "startxref":
                        // 下一行是交叉表偏移量
                        line = lines[i + 1];
                        if (Int32.TryParse(line, out var val))
                        {
                            result.StartXref = val;
                            i++;
                        }
                        else
                        {
                            throw new Exception("期待接收一个数字");
                        }
                        break;
                    default:
                        {
                            if (line.StartsWith("trailer"))
                            {
                                var objstr2 = new List<String>();
                                lines[i] = lines[i][7..];
                                do
                                {
                                    line = lines[i];
                                    objstr2.Add(line);
                                    if (line.EndsWith(">>"))
                                    {
                                        break;
                                    }
                                    i++;
                                }
                                while (true);
                                var dic2 = ParseFileTrailerObject(String.Join(' ', objstr2));
                                result.TrailerObj = dic2;
                            }
                        }
                        break;
                }
            }

            return result;
        }

        /// <summary>
        /// 处理文件尾部字典
        /// </summary>
        /// <param name="psCode"></param>
        /// <returns></returns>
        [Obsolete("建议使用 PSCompilationEngineV2 相关方法")]
        private static Dictionary<String, Object> ParseFileTrailerObject(String psCode)
        {
            // 斜杆 空格 [ < 开启新Token
            var engine = new PSCompilationEngine();
            var tokens = engine.GetPSTokens(psCode, Encoding.GetBytes(psCode));
            var dic = engine.ParseToDictionary(tokens);
            return dic;
        }

        /// <summary>
        /// 读取指定偏移量的pdf文件对象
        /// </summary>
        /// <param name="pdf"></param>
        /// <param name="offset"></param>
        /// <returns></returns>
        internal static PdfFileObject? ParseFileObject(Stream pdf, Int32 offset)
        {
            var engine = new PSCompilationEngineV2();
            engine.ParseToPdfFileObject(pdf, offset);
            var fileObj = engine.PdfFileObject;
            return fileObj;
        }

        /// <summary>
        /// 读取所有的可用对象
        /// </summary>
        /// <param name="pdf"></param>
        /// <param name="xrefInfos"></param>
        /// <returns></returns>
        internal static List<PdfFileObject> ParseFileObjects(Stream pdf, XRefTable[] xrefInfos)
        {
            var result = new List<PdfFileObject>();
            foreach (var xrefInfo in xrefInfos)
            {
                for (var objIdx = 0; objIdx < xrefInfo.ObjOffsetInfos.Count; objIdx++)
                {
                    var item = xrefInfo.ObjOffsetInfos[objIdx];
                    if (item.RefFlag != 'n')
                    {
                        // 过时对象
                        continue;
                    }
                    var obj = ParseFileObject(pdf, item.Offset);
                    result.Add(obj);
                }
            }
            return result;
        }

        /// <summary>
        /// 目前假设 对象的开始 一定是一个字典或者数组
        /// 如果开始是个数组 则一定没有字节流
        /// </summary>
        /// <param name="binLine"></param>
        /// <returns></returns>
        [Obsolete("建议使用 PSCompilationEngineV2 相关方法")]
        private static (string psCode, Byte[] psCodeByte, List<byte> binArr) ParseFileObjectBody(List<Byte[]> binLine)
        {
            var psCode = new StringBuilder();
            var psCodeArr = new List<Byte>();
            var binArr = new List<Byte>();
            var indic = false;
            var inbin = false;
            if (binLine[0][0] == '[')
            {
                // 数组
                // [122 0 R/XYZ 264.55 741.3 0]
                for (int i = 0; i < binLine.Count; i++)
                {
                    var currLine = binLine[i];
                    var strLine = Encoding.GetString(currLine);
                    psCode.Append(strLine);
                    psCodeArr.AddRange(currLine);
                    if (!strLine.EndsWith(']'))
                    {
                        psCode.Append(' ');
                        psCodeArr.Add((Byte)' ');
                    }
                }
            }
            else
            {
                // 字典
                for (int i = 0; i < binLine.Count; i++)
                {
                    // <<>> stream endstream
                    var currLine = binLine[i].AsSpan();
                    if (inbin)
                    {
                        if (currLine.Length == 9
                            && currLine[0] == 0x65 // e
                            && currLine[1] == 0x6E // n
                            && currLine[2] == 0x64 // d
                            && currLine[3] == 0x73 // s
                            && currLine[4] == 0x74 // t
                            && currLine[5] == 0x72 // r
                            && currLine[6] == 0x65 // e
                            && currLine[7] == 0x61 // a
                            && currLine[8] == 0x6D // m
                            )
                        {
                            inbin = false;
                        }
                        binArr.AddRange(binLine[i]);
                    }
                    else
                    {
                        var strLine = Encoding.GetString(currLine).Trim('\n').Trim('\r');
                        // >> stream
                        // 
                        if (!indic && strLine.StartsWith("<<"))
                        {
                            // >> 后面只能是  >>stream >>\nstream
                            if (strLine.EndsWith(">>"))
                            {
                                if (i + 2 > binLine.Count)
                                {
                                    // 结束了
                                    psCode.Append(strLine);
                                    psCodeArr.AddRange(currLine.TrimEnd((Byte)'\n').TrimEnd((Byte)'\r'));
                                }
                                else
                                {
                                    var nextLine = Encoding.GetString(binLine[i + 1]);
                                    if (nextLine.StartsWith("stream"))
                                    {
                                        inbin = true;
                                        indic = false;
                                        // 结束了
                                        var idxend = strLine.LastIndexOf(">>");
                                        psCode.Append(strLine.Substring(0, idxend + 2));
                                        var idxendByte = currLine.LastIndexOf((Byte)'>');
                                        if (currLine[idxendByte - 1] == (Byte)'>')
                                        {
                                            psCodeArr.AddRange(currLine.Slice(0, idxendByte + 1));
                                        }
                                        i++;
                                    }
                                }
                            }
                            else if (strLine.EndsWith(">>stream"))
                            {
                                inbin = true;
                                indic = false;
                                // 结束了
                                var idxend = strLine.LastIndexOf(">>");
                                psCode.Append(strLine.Substring(0, idxend + 2));
                                var idxendByte = currLine.LastIndexOf((Byte)'>');
                                if (currLine[idxendByte - 1] == (Byte)'>')
                                {
                                    psCodeArr.AddRange(currLine.Slice(0, idxendByte + 1));
                                }
                            }
                            else
                            {
                                // 没结束
                                psCode.Append(strLine);
                                psCode.Append(' ');
                                psCodeArr.AddRange(currLine.TrimEnd((Byte)'\n').TrimEnd((Byte)'\r'));
                                psCodeArr.Add((Byte)' ');
                                indic = true;
                            }
                        }
                        else
                        {
                            if (indic)
                            {
                                // >> 后面只能是  >>stream >>\nstream
                                if (strLine.EndsWith(">>"))
                                {
                                    if (i + 2 > binLine.Count)
                                    {
                                        inbin = false;
                                        indic = false;
                                        // 结束了
                                        psCode.Append(strLine);
                                        psCodeArr.AddRange(currLine.TrimEnd((Byte)'\n').TrimEnd((Byte)'\r'));
                                    }
                                    else
                                    {
                                        var nextLine = Encoding.GetString(binLine[i + 1]);
                                        if (nextLine.StartsWith("stream"))
                                        {
                                            // 结束了
                                            var idxend = strLine.LastIndexOf(">>");
                                            psCode.Append(strLine.Substring(0, idxend + 2));
                                            var idxendByte = currLine.LastIndexOf((Byte)'>');
                                            if (currLine[idxendByte - 1] == (Byte)'>')
                                            {
                                                psCodeArr.AddRange(currLine.Slice(0, idxendByte + 1));
                                            }
                                            inbin = true;
                                            indic = false;
                                            i++;
                                        }
                                        else
                                        {
                                            // 没结束
                                            psCode.Append(strLine);
                                            psCode.Append(' ');
                                            psCodeArr.AddRange(currLine.TrimEnd((Byte)'\n').TrimEnd((Byte)'\r'));
                                            psCodeArr.Add((Byte)' ');
                                            indic = true;
                                        }
                                    }
                                }
                                else if (strLine.EndsWith(">>stream"))
                                {
                                    // 结束了
                                    psCode.Append(strLine);
                                    psCodeArr.AddRange(currLine.TrimEnd((Byte)'\n').TrimEnd((Byte)'\r'));
                                    inbin = true;
                                    indic = false;
                                }
                                else
                                {
                                    // 没结束
                                    psCode.Append(strLine);
                                    psCode.Append(' ');
                                    psCodeArr.AddRange(currLine.TrimEnd((Byte)'\n').TrimEnd((Byte)'\r'));
                                    psCodeArr.Add((Byte)' ');
                                    indic = true;
                                }
                            }
                        }
                    }
                }
            }
            return (psCode.ToString(), psCodeArr.ToArray(), binArr);
        }

        /// <summary>
        /// xref 读取
        /// </summary>
        /// <param name="pdf"></param>
        /// <param name="startXref"></param>
        /// <returns></returns>
        [Obsolete("建议使用 ParseXRef2andTailerV3")]
        private static (XRefTable[], Dictionary<String, Int32> map, PdfFileObject? tailerObj) ParseXref(Stream pdf, Int32 startXref)
        {
            // 从 startXref 指定的偏移量开始读取交叉表
            // 第一行是对象的个数
            // 第二行 常量 0000000000 65535 f 
            // 从第三行开始是各个对象的偏移量
            // 0000436406 00000 n 

            // 文件的情况
            // ....
            // endobj
            // xref
            // 0 805
            // 0000000000 65535 f
            // 0000436406 00000 n
            // 0000176418 00000 n
            // 0000168511 00000 n
            // ....
            // 例外情况 xref表是一个字典 此时不通过原有方式读取xref表
            var first = ReadLine(pdf, 22);
            if(first.Length == 4)
            {
                List<XRefTable> xRefTables = [];
                pdf.Seek(startXref + 4, SeekOrigin.Begin);
                XRefTable xRefTable = null;
                while (true)
                {
                    //span.Clear();
                    var buff = ReadLine(pdf, 22);
                    if (buff.Length < 4)
                    {
                        continue;
                    }
                    var line = Encoding.GetString(buff);
                    if (line.StartsWith("trailer"))
                    {
                        // 移动回去
                        pdf.Position = pdf.Position - buff.Length;
                        break;
                    }
                    var xrefarr = line.Split(' ');
                    Int32.TryParse(xrefarr[0], out Int32 val1);
                    Int32.TryParse(xrefarr[1], out Int32 val2);

                    if (xrefarr.Length == 2)
                    {
                        xRefTable = new XRefTable(val1, val2);
                        xRefTables.Add(xRefTable);
                    }
                    else
                    {
                        var refId = xRefTable.StartId + xRefTable.ObjOffsetInfos.Count;
                        xRefTable.ObjOffsetInfos.Add(new ObjOffsetInfo
                        {
                            Offset = val1,
                            Version = val2,
                            RefFlag = xrefarr[2][0],
                            RefId = refId
                        });
                    }
                }
                var dic = new Dictionary<String, Int32>();
                foreach (var xrefTable in xRefTables)
                {
                    for (var i = 0; i < xrefTable.ObjOffsetInfos.Count; i++)
                    {
                        var xref = xrefTable.ObjOffsetInfos[i];
                        dic.Add($"{xref.RefId} 0", xref.Offset);
                    }
                }
                return (xRefTables.ToArray(), dic, null);
            }
            else
            {
                var offset = startXref;
                List<XRefTable> xRefTables = [];
                while (true)
                {
                    var engine = new PSCompilationEngineV2();
                    engine.ParseToPdfFileObject(pdf, offset);
                    var fileObj = engine.PdfFileObject;

                    xRefTables.AddRange(ParseXrefByStream(fileObj));


                    // 一定是一个字典 包含了二进制流
                    if(fileObj.TryGetValue(PdfName.Key_Prev, out var _val) && Int32.TryParse(_val.ToString(), out var _val2))
                    {
                        offset = _val2;
                    }
                    else
                    {
                        break;
                    }
                }

                var dic = new Dictionary<String, Int32>();
                foreach (var xrefTable in xRefTables)
                {
                    for (var i = 0; i < xrefTable.ObjOffsetInfos.Count; i++)
                    {
                        var xref = xrefTable.ObjOffsetInfos[i];
                        var key = $"{xref.RefId} 0";
                        // 后生成的对象信息覆盖前面的所以TryAdd
                        dic.TryAdd(key, xref.Offset);
                    }
                }
                return (xRefTables.ToArray(), dic, null);
            }
        }

        private static List<XRefTable> ParseXrefByStream(PdfFileObject fileObj)
        {
            //  /Type 
            if(!fileObj.TryGetValue(PdfName.Key_Type, out var _type) || _type.ToString() != PdfTypeConst.Type_XRef)
            {
                return [];
            }
            // /W /Root /Size /Index
            Int32[] wFlag = [];
            if(fileObj.TryGetValue(PdfName.Key_W, out var _w))
            {
                wFlag = ParseList<Int32>(_w, Trans2Int32, fileObj).ToArray();
            }
            if(wFlag.Length != 3)
            {
                throw new Exception("查找xrefsize失败 wFlag.Length != 3");
            }
            Int32 _size = 0;
            if (fileObj.TryGetValue(PdfName.Key_Size, out var __size))
            {
                _size = ParseInt32(__size, fileObj);
            }
            else
            {
                throw new Exception("查找xrefsize失败");
            }

            List<XRefTable> xRefTables = [];
            var dic = new Dictionary<String, Int32>();
            Int32[] intArr;
            if(fileObj.TryGetValue(PdfName.Key_Index, out var _idx))
            {
                intArr = ParseList<Int32>(_idx, Trans2Int32, fileObj).ToArray();
            }
            else
            {
                intArr = [0, _size];
            }


            var ptr = 0;
            ReadOnlySpan<Byte> dataSp = fileObj.DecodeStreamData.AsSpan();
            for (var i = 0; i < intArr.Length; i++, i++)
            {
                var startNo = intArr[i];
                var currNo = startNo;
                var objCount = intArr[i + 1];
                var xRefTable = new XRefTable(startNo, objCount);
                xRefTables.Add(xRefTable);
                for (var objIdx = 0; objIdx < objCount; objIdx++)
                {
                    var enableFlag = wFlag[0] > 0 ? 0 : 1;
                    for(var j = 0; j < wFlag[0]; j++)
                    {
                        enableFlag = (enableFlag << 8) + dataSp[ptr++];
                    }
                    var num6 = 0;
                    for (var j = 0; j < wFlag[1]; j++)
                    {
                        num6 = (num6 << 8) + dataSp[ptr++];
                    }
                    var num7 = 0;
                    for (var j = 0; j < wFlag[2]; j++)
                    {
                        num7 = (num7 << 8) + dataSp[ptr++];
                    }
                    switch (enableFlag)
                    {
                        case 0:
                            break;
                        case 1:
                            xRefTable.ObjOffsetInfos.Add(new ObjOffsetInfo
                            {
                                RefId = currNo,
                                Offset = num6,
                            });
                            break;
                        case 2:
                            xRefTable.ObjOffsetInfos.Add(new ObjOffsetInfo
                            {
                                RefId = currNo, // objNum
                                ObjStmId = num6,
                                Index = num7,
                            });
                            // 暂时不处理
                            break;
                    }
                    currNo++;
                }
            }
            return xRefTables;
        }

        /// <summary>
        /// 读取一行 保留换行符号
        /// 长度为0 就是到文件结尾了
        /// </summary>
        /// <param name="pdf"></param>
        /// <returns></returns>
        private static Byte[] ReadLine(Stream pdf, Int32 recommend = 100)
        {
            var result = new List<Byte>(recommend);

            // 参考文本读取读行的方法
            var buff = new Byte[256];
            var buffSpan = new Span<Byte>(buff);
            while (true)
            {
                buffSpan.Clear();
                var t = pdf.Read(buffSpan);
                if (t == 0)
                {
                    break;
                }

                var idxOfNewline = -1;
                var igLen = 0;
                do
                {
                    var rng = buffSpan.Slice(igLen);
                    if (rng.Length < 1)
                    {
                        // 长度为0
                        // 最终没找到
                        break;
                    }
                    var _idxOfNewline = rng.IndexOfAny((Byte)'\r', (Byte)'\n');
                    if (_idxOfNewline == -1)
                    {
                        // 剩余长度中没找到
                        break;
                    }
                    if (_idxOfNewline > 0 && rng[_idxOfNewline - 1] == 92)
                    {
                        // \\n 不属于换行
                        igLen += _idxOfNewline + 1;
                    }
                    else
                    {
                        // 找到了
                        idxOfNewline = _idxOfNewline + igLen;
                        break;
                    }
                } while (true);

                if (idxOfNewline > -1)
                {
                    Byte matcherChar = buffSpan[idxOfNewline];
                    if (matcherChar == (Byte)'\r')
                    {
                        // 如果是 '\r' 需要处理紧随的'\n'
                        if (idxOfNewline < 255)
                        {
                            // 需要处理的情况在当前的buff中就可以处理
                            if (buffSpan[idxOfNewline + 1] == '\n')
                            {
                                idxOfNewline++;
                            }
                            result.AddRange(buffSpan.Slice(0, idxOfNewline + 1));
                            pdf.Position = pdf.Position - t + idxOfNewline + 1;
                        }
                        else
                        {
                            //>=255 255
                            // 读取一个字节处理即可
                            var nextData = pdf.ReadByte();
                            result.AddRange(buffSpan.Slice(0, buffSpan.Length));
                            if (nextData > -1 && nextData == '\n')
                            {
                                result.Add((Byte)'\n');
                            }
                        }
                    }
                    else
                    {
                        result.AddRange(buffSpan.Slice(0, idxOfNewline + 1));
                        pdf.Position = pdf.Position - t + idxOfNewline + 1;
                    }
                    break;
                }
                else
                {
                    result.AddRange(buffSpan.Slice(0, buffSpan.Length));
                }
            }
            return [.. result];
        }

        /// <summary>
        /// 从尾部按行读取文件
        /// </summary>
        /// <param name="pdf"></param>
        /// <returns></returns>
        private static Byte[] ReadLineBack(Stream pdf)
        {
            var stack = new Stack<Byte>();
            var oneByteArray = new Byte[1];
            while (true)
            {
                var b = pdf.Read(oneByteArray, 0, 1);
                pdf.Position--;
                pdf.Position--;
                // 考虑到了文件第一个字节的情况
                if (b == 0)
                {
                    break;
                }
                if (oneByteArray[0] == '\n')
                {
                    // 看下前面是不是 \r
                    b = pdf.Read(oneByteArray, 0, 1);
                    if (b == 0)
                    {
                        break;
                    }
                    pdf.Position--;
                    if(oneByteArray[0] == '\r')
                    {
                        pdf.Position--;
                    }
                    break;
                }
                if(oneByteArray[0] == '\r')
                {
                    break;
                }
                stack.Push(oneByteArray[0]);
            }
            var result = new Byte[stack.Count];
            for (var i = 0; i < result.Length; i++)
            {
                result[i] = stack.Pop();
            }
            return result;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static Boolean ParseBoolean(Object obj, PdfFileObject pdfFileObject) 
        {
            if (obj is String str)
            {
                if (str.EndsWith(" R"))
                {
                    var _obj = pdfFileObject.GetIndirectObj(str);
                    if (_obj.Value != null && _obj.Value is Boolean v)
                    {
                        return v;
                    }
                    return default;
                }
                else
                {
                    _ = Boolean.TryParse(obj?.ToString(), out var val);
                    return val;
                }
            }
            return false;
            //if (obj == null) return false;
            //_ = Boolean.TryParse(obj?.ToString(), out var val);
            //return val;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static Int32 ParseInt32(Object obj, PdfFileObject pdfFileObject) 
        {
            if (obj is String str)
            {
                if(str.EndsWith(" R"))
                {
                    var _obj = pdfFileObject.GetIndirectObj(str);
                    if(_obj.Value != null && _obj.Value is Int32 v)
                    {
                        return v;
                    }
                    return default;
                }
                else
                {
                    _ = Int32.TryParse(obj?.ToString(), out var val);
                    return val;
                }
            }
            return default;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static Double ParseDouble(Object obj, PdfFileObject pdfFileObject) 
        {
            if (obj is String str)
            {
                if (str.EndsWith(" R"))
                {
                    var _obj = pdfFileObject.GetIndirectObj(str);
                    if (_obj.Value != null && _obj.Value is Double v)
                    {
                        return v;
                    }
                    return default;
                }
                else
                {
                    _ = Double.TryParse(obj?.ToString(), out var val);
                    return val;
                }
            }
            return default;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static String? ParseString(Object obj) 
        {
            var str = obj?.ToString();
            if(str == null)
            {
                return null;
            }
            if (str[0] == '(')
            {
                return str[1..^1];
            }
            else if (str[0] == '<')
            {
                // TODO 对于16进制表示的字符串需要处理
                return str[1..^1];
            }
            else
            {
                return str;
            }
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static DateTime? ParseDateTime(Object obj) 
        {
            var str = obj.ToString();
            if (str == null || str.Length < 8)
            {
                // 最少需要有年份的部分
                return null;
            }
            // 忽略空格
            // YYYY 年份，有四位数，例如2008年
            // MM  月份，从01到12的两位数
            // DD  天数，从01到31的两位数
            // HH  小时，从00到23的两位数
            // mm  分钟，从00到59两位数
            // SS  秒钟，从00到59两位数
            // O   本地时间与世界时的关系，+，-或Z. + 表示本地时间晚于UT， -更早，Z等于世界时
            // HH’	世界时的偏差绝对值，以小时为单位，以00到23的两位数表示
            // mm’	通用时间偏移的绝对值，以分钟为单位，从00到59两位数
            // (D: 2006 09 26 21 39 13 + 02' 00')
            // (D: YYYY MM DD HH mm SS O HH' mm')
            // YYYYMMDDHHmmSSOHH'mm'
            if (str.StartsWith("(D:") && str.EndsWith(')'))
            {
                var _str = str[3..^1];
                if(_str.Length > 13)
                {
                    _str = $"{_str.Substring(0, 4)}/{_str.Substring(4, 2)}/{_str.Substring(6, 2)} {_str.Substring(8, 2)}:{_str.Substring(10, 2)}:{_str.Substring(12, 2)}";
                }
                else if (_str.Length > 11)
                {
                    _str = $"{_str.Substring(0, 4)}/{_str.Substring(4, 2)}/{_str.Substring(6, 2)} {_str.Substring(8, 2)}:{_str.Substring(10, 2)}:00";
                }
                else if (_str.Length > 9)
                {
                    _str = $"{_str.Substring(0, 4)}/{_str.Substring(4, 2)}/{_str.Substring(6, 2)} {_str.Substring(8, 2)}:00:00";
                }
                else if (_str.Length > 7)
                {
                    _str = $"{_str.Substring(0, 4)}/{_str.Substring(4, 2)}/{_str.Substring(6, 2)} 00:00:00";
                }
                else if (_str.Length > 5)
                {
                    _str = $"{_str.Substring(0, 4)}/{_str.Substring(4, 2)}/01 00:00:00";
                }
                else
                {
                    _str = $"{_str.Substring(0, 4)}/01/01 00:00:00";
                }
                _ = DateTime.TryParse(_str, out var val);
                return val;
            }
            else
            {
                return null;
            }
        }

        internal static List<T> ParseList<T>(Object val, Func<Object, T> trans, PdfFileObject pdfFileObject)
        {
            if (val is IList<T> _val)
            {
                return _val.ToList();
            }
            else if (val is IList _val2) 
            {
                var re = new List<T>(_val2.Count);
                foreach (var item in _val2)
                {
                    re.Add(trans(item));
                }
                return re;
            }
            else if (val is PdfFileObject _val3)
            {
                var re = new List<T>(_val3.List.Count);
                foreach (var item in _val3.List)
                {
                    re.Add(trans(item));
                }
                return re;

            }
            else if (val is String str && str.EndsWith(" R"))
            {
                var obj = pdfFileObject.GetIndirectObj(str);
                var re = new List<T>(obj.List.Count);
                foreach (var item in obj.List)
                {
                    re.Add(trans(item));
                }
                return re;
            }
            return val == null ? null : [];
        }

        public static Func<Object, Object> Trans2Object = p => p;
        public static Func<Object, String> Trans2String = p => p.ToString();
        public static Func<Object, Int32> Trans2Int32 = p => Int32.Parse(p.ToString());
        public static Func<Object, Double> Trans2Double = p => Double.Parse(p.ToString());
        public static Func<Object, Single> Trans2Single = p => Single.Parse(p.ToString());

        internal static Dictionary<String, Object> ParseDictionary(Object val, PdfFileObject pdfFileObject)
        {
            if (val is Dictionary<String, Object> _val)
            {
                return _val;
            }
            else if (val is PdfFileObject fileObject)
            {
                return fileObject.Dictionary;
            }
            else if(val is String str && str.EndsWith(" R"))
            {
                var obj = pdfFileObject.GetIndirectObj(str);
                return obj.Dictionary;
            }
            return val == null ? null : [];
        }
    }
}
